﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using NewsMine.DomainObjects;
using NewsMine.Utilities;
using WebApp1.Controllers;

namespace WebApp1.Models
{
    public class CategoryMaster
    {
        public static string[] GetAvailableCategories()
        {
            string[] categories = {
                                    "LatestNews",
                                    "TopStories",
                                    "India",
                                    "Regional",
                                    "World",
                                    "Business",
                                    "Entertainment",
                                    "Sports",
                                    "Health",
                                    "LifeStyle",
                                    "SciTech",
                                    "AutoMobiles",
                                    "Astrology",
                                    "Local"
                                    };

            return categories;

        }

    }



    public class GroupingManager
    {
        class FeedConnection
        {
            public string Source { get; set; }
            public string Destination { get; set; }
            public double Score { get; set; }
            public List<string> Matchedkeywords { get; set; }
        }

        class keyValue
        {
            public string Key { set; get; }
            public int NumberOfTokens { set; get; }
            public int Value { set; get; }
        }

        public static List<FeedGroup> CreateFeedGroupsV2(List<FeedItem> feeds, double similarity = 0.4)
        {
            List<string> uniqueFeedIds = (from f in feeds
                                          select f.ID).ToList();

            int feedsCount = feeds.Count;

            Dictionary<int, List<double>> scoresAgainstFeedIndex = new Dictionary<int, List<double>>();


            List<FeedConnection> feedConnections = new List<FeedConnection>();

            for (int i = 0; i < feedsCount; i++)
            {
                for (int j = 0; j < feedsCount; j++)
                {
                    if (i == j)
                        continue;
                    string source = TempAnalyzer.CleanString(feeds[i].Title, true, false, true, true);
                    string dest = TempAnalyzer.CleanString(feeds[j].Title, true, false, true, true);
                    var score = NewsMine.Utilities.CosineSimilarity.FindSimilarity(source, dest);

                    FeedConnection fc = new FeedConnection { Source = feeds[i].ID, Destination = feeds[j].ID, Score = score };

                    feedConnections.Add(fc);
                }
            }

            var resultedStrongFeedConnections = new List<FeedConnection>();

            for (int i = 0; i < feedsCount; i++)
            {
                var sourceScores = feedConnections.Where(fc => fc.Source == feeds[i].ID).ToList();

                if (sourceScores.Count == 0)
                    continue;

                var topScore = (from score in sourceScores orderby score.Score descending select score).First();

                resultedStrongFeedConnections.Add(topScore);
            }

            //foreach (var fc in resultedStrongFeedConnections)
            //{
            //    Response.Write("<br/>" + fc.Source + " - " + fc.Destination + " - " + fc.Score);
            //}

            //Response.Write("<hr/>");



            Dictionary<string, FeedConnection> dedupeDictionary = new Dictionary<string, FeedConnection>();

            foreach (var score in resultedStrongFeedConnections)
            {
                string key = string.Join(",", (new string[] { score.Source, score.Destination }).OrderBy(f => f)) + score.Score.ToString();
                if (dedupeDictionary.ContainsKey(key) == false)
                {
                    dedupeDictionary.Add(key, score);
                }
            }

            resultedStrongFeedConnections.Clear();

            foreach (var item in dedupeDictionary)
            {
                resultedStrongFeedConnections.Add(item.Value);
            }


            //foreach (var fc in resultedStrongFeedConnections)
            //{
            //    Response.Write("<br/>" + fc.Source + " - " + fc.Destination + " - " + fc.Score);
            //}

            //Response.Write("<hr/>");

            var groupss = (from sc in resultedStrongFeedConnections
                           group sc by sc.Destination
                               into scg
                               select new { Parent = scg.Key, Children = scg.ToList().Where(s => s.Score > similarity).ToList() }).ToList();

            List<WebApp1.Controllers.FeedGroup> groups = new List<Controllers.FeedGroup>();

            List<string> selectedFeedsForGroups = new List<string>();

            foreach (var g in groupss)
            {
                //Response.Write("<hr/>");
                if (g.Children.Count == 0)
                    continue;

                var similarItems = (from c in g.Children
                                    orderby c.Score descending
                                    select c).ToList();

                FeedGroup fg = new FeedGroup();
                fg.Feeds = new List<FeedItem>();

                var mainFeed = feeds.Where(f => f.ID == g.Parent).First();

                fg.Feeds.Add(mainFeed);

                // Response.Write("<br/><b>" + mainFeed.Title + "</b>");
                foreach (var simItem in similarItems)
                {
                    var selectedFeeds = feeds.Where(f => f.ID == simItem.Source).ToList();

                    fg.Feeds.AddRange(selectedFeeds);


                    //foreach (var sFeed in selectedFeeds)
                    //{
                    //    Response.Write("<br/>" + sFeed.Title);
                    //}
                    //Response.Write("Score : " + simItem.Score + "<br/>");
                }

                //get the better image for group

                var feedForGroupInfo = (from f in fg.Feeds
                                        orderby f.ImageWidth descending
                                        select f
                                            ).FirstOrDefault();

                if (feedForGroupInfo != null)
                {
                    fg.Domain = feedForGroupInfo.Domain;
                    fg.ImageHeight = feedForGroupInfo.ImageHeight;
                    fg.ImageUrl = feedForGroupInfo.ImageUrl;
                    fg.ImageWidth = feedForGroupInfo.ImageWidth;
                    fg.Date = fg.Feeds.Max(f => f.PubDate);
                }

                groups.Add(fg);

                selectedFeedsForGroups.AddRange(fg.Feeds.Select(fdd => fdd.ID).ToList());

            }

            //return groups;

            feeds = feeds.Where(f => !selectedFeedsForGroups.Contains(f.ID)).ToList();


            List<WebApp1.Controllers.FeedGroup> remaingGroups = (from f in feeds
                                                                 group f by new
                                                                 {
                                                                     f.ImageUrl,
                                                                     f.ImageWidth,
                                                                     f.ImageHeight,
                                                                     f.Domain,
                                                                 }
                                                                     into gfeeds
                                                                     select new WebApp1.Controllers.FeedGroup
                                                                     {
                                                                         Feeds = gfeeds.ToList(),
                                                                         Date = gfeeds.Max(f => f.PubDate),
                                                                         ImageUrl = gfeeds.Key.ImageUrl,
                                                                         ImageHeight = gfeeds.Key.ImageHeight,
                                                                         ImageWidth = gfeeds.Key.ImageWidth,
                                                                         Domain = gfeeds.Key.Domain
                                                                     }).ToList();




            remaingGroups.AddRange(groups);

            return remaingGroups;

            //foreach (var item in resultedStrongFeedConnections)
            //{
            //    Response.Write("<br/>" + item.Source + " - " + item.Destination + " - " + item.Score);
            //    if (item.Score > 0)
            //    {
            //        var selectedFeeds = feeds.Where(f => f.ID == item.Destination || f.ID == item.Source).ToList();

            //        foreach (var sFeed in selectedFeeds)
            //        {
            //            Response.Write("<br/>" + sFeed.Title);
            //        }
            //    }
            //}

        }


        public static List<FeedGroup> CreateFeedGroupsV3(QResult totalContextResults, double similarity = 0.5)
        {
            var feeds = totalContextResults.FeedItems;
            //int numberOfPastHours = 10;
            //List<KeyWordTokenDensity> kvDensityInfoList = NewsDiscoveryEngine.Index.KeywordDensityInfoManager.GetKeyWordDensityByChannelName(totalContextResults.SearchString, numberOfPastHours, "title");

            //List<string> densifiedKeywordList = (from kvd in kvDensityInfoList
            //                                     where kvd.Score >= 0.09999
            //                                     select kvd.TokenName.Trim().ToLower()).ToList();

            //totalContextResults.IsDisableGrouping = true;

            if (totalContextResults.IsDisableGrouping == true)
            {
                var resultedFeedGroups = (from f in feeds
                                          group f by new
                                          {
                                              f.ImageUrl,
                                              //f.AnalyzedTag,
                                              f.ImageWidth,
                                              f.ImageHeight,
                                              f.Domain,
                                              
                                          }
                                              into gfeeds
                                              select new WebApp1.Controllers.FeedGroup
                                              {
                                                  Feeds = gfeeds.ToList(),
                                                  Date = gfeeds.Max(f => f.PubDate),
                                                  ImageUrl = gfeeds.Key.ImageUrl,
                                                  ImageHeight = gfeeds.Key.ImageHeight,
                                                  ImageWidth = gfeeds.Key.ImageWidth,
                                                  Domain = gfeeds.Key.Domain
                                              }).ToList();

                return resultedFeedGroups;
            }


            List<string> uniqueFeedIds = (from f in feeds
                                          select f.ID).ToList();

            int feedsCount = feeds.Count;

            Dictionary<int, List<double>> scoresAgainstFeedIndex = new Dictionary<int, List<double>>();


            List<FeedConnection> feedConnections = new List<FeedConnection>();
            SimilarityTool simTool = new SimilarityTool();
            for (int i = 0; i < feedsCount; i++)
            {
                for (int j = 0; j < feedsCount; j++)
                {
                    if (i == j)
                        continue;
                    string source = TempAnalyzer.CleanString(feeds[i].Title, true, false, true, true);
                    string dest = TempAnalyzer.CleanString(feeds[j].Title, true, false, true, true);

                    //source = String.Join(" ", source.Split(' ').Intersect(densifiedKeywordList).ToList());
                    //dest = String.Join(" ", dest.Split(' ').Intersect(densifiedKeywordList).ToList());



                    var score = NewsMine.Utilities.CosineSimilarity.FindSimilarity(source, dest);



                    score = simTool.CompareStrings(source, dest);

                    FeedConnection fc = new FeedConnection { Source = feeds[i].ID, Destination = feeds[j].ID, Score = score };

                    feedConnections.Add(fc);
                }
            }

            var resultedStrongFeedConnections = new List<FeedConnection>();

            for (int i = 0; i < feedsCount; i++)
            {
                var sourceScores = feedConnections.Where(fc => fc.Source == feeds[i].ID).ToList();

                if (sourceScores.Count == 0)
                    continue;

                var topScore = (from score in sourceScores orderby score.Score descending select score).First();

                resultedStrongFeedConnections.Add(topScore);
            }

            Dictionary<string, FeedConnection> dedupeDictionary = new Dictionary<string, FeedConnection>();

            foreach (var score in resultedStrongFeedConnections)
            {
                string key = string.Join(",", (new string[] { score.Source, score.Destination }).OrderBy(f => f)) + "," + score.Score.ToString();
                if (dedupeDictionary.ContainsKey(key) == false)
                {
                    dedupeDictionary.Add(key, score);
                }
            }

            resultedStrongFeedConnections.Clear();

            foreach (var item in dedupeDictionary)
            {
                resultedStrongFeedConnections.Add(item.Value);
            }

            var groupss = (from sc in resultedStrongFeedConnections
                           group sc by sc.Destination
                               into scg
                               select new { Parent = scg.Key, Children = scg.ToList().Where(s => s.Score > similarity).ToList() }).ToList();

            List<WebApp1.Controllers.FeedGroup> groups = new List<Controllers.FeedGroup>();

            List<string> selectedFeedsForGroups = new List<string>();

            foreach (var g in groupss)
            {
                //Response.Write("<hr/>");
                if (g.Children.Count == 0)
                    continue;

                var similarItems = (from c in g.Children
                                    orderby c.Score descending
                                    select c).ToList();

                FeedGroup fg = new FeedGroup();
                fg.Feeds = new List<FeedItem>();

                var mainFeed = feeds.Where(f => f.ID == g.Parent).First();

                fg.Feeds.Add(mainFeed);

                // Response.Write("<br/><b>" + mainFeed.Title + "</b>");
                foreach (var simItem in similarItems)
                {
                    var selectedFeeds = feeds.Where(f => f.ID == simItem.Source).ToList();

                    fg.Feeds.AddRange(selectedFeeds);
                }

                //get the better image for group
                var feedForGroupInfo = (from f in fg.Feeds
                                        orderby f.ImageWidth descending
                                        select f
                                            ).FirstOrDefault();

                if (feedForGroupInfo != null)
                {
                    fg.Domain = feedForGroupInfo.Domain;
                    fg.ImageHeight = feedForGroupInfo.ImageHeight;
                    fg.ImageUrl = feedForGroupInfo.ImageUrl;
                    fg.ImageWidth = feedForGroupInfo.ImageWidth;
                    fg.Date = fg.Feeds.Max(f => f.PubDate);
                }

                fg.Feeds = (from f in fg.Feeds orderby f.PubDate descending select f).ToList();

                fg.Feeds.Remove(feedForGroupInfo);
                fg.Feeds.Insert(0, feedForGroupInfo);

                groups.Add(fg);

                selectedFeedsForGroups.AddRange(fg.Feeds.Select(fdd => fdd.ID).ToList());

            }

            for (int i = 0; i < groups.Count; i++)
            {
                for (int j = 0; j < groups.Count; j++)
                {
                    if (groups[i] == groups[j])
                        continue;

                    if (groups[i] == null || groups[j] == null || groups[i].Feeds.Count == 0 || groups[j].Feeds.Count == 0)
                        continue;

                    var connectingItems = groups[i].Feeds.Select(f => f.ID).ToList().Intersect(groups[j].Feeds.Select(fToCompare => fToCompare.ID).ToList());


                    if (connectingItems.Count() > 0)
                    {
                        groups[i].Feeds.AddRange(groups[j].Feeds.Where(f => !connectingItems.Contains(f.ID)));

                        groups[j].Feeds.Clear();
                    }

                }
            }

            groups = (from g in groups
                      where g.Feeds.Count > 0
                      select g).ToList();



            //Score calculation
            //Lets not depend on the keyword density metrics for now... we will do it with the groups feeds metrics

            for (int i = 0; i < groups.Count; i++)
            {
                int numberOfWebSites = groups[i].Feeds.Select(f => f.Domain).Distinct().Count();
                int numberOfNewsItems = groups[i].Feeds.Count;
                groups[i].Score = numberOfWebSites * numberOfNewsItems * 1.0;
            }


            //for (int i = 0; i < groups.Count; i++)
            //{
            //    List<string> tokensForScoring = TempAnalyzer.CleanString(String.Join(",", groups[i].Feeds.Select(fd => fd.Title.ToLower()).ToList()), true, false, true, true).Split(' ').Intersect(densifiedKeywordList).Distinct().ToList();

            //    if (tokensForScoring != null && tokensForScoring.Count > 0)
            //    {
            //        groups[i].Score = (from kvd in kvDensityInfoList
            //                           where tokensForScoring.Contains(kvd.TokenName)
            //                           select kvd.Score).ToList().Aggregate(1.0, (x, y) => x + y);
            //    }
            //}

            //return groups;

            feeds = feeds.Where(f => !selectedFeedsForGroups.Contains(f.ID)).ToList();


            List<WebApp1.Controllers.FeedGroup> remaingGroups = (from f in feeds
                                                                 group f by new
                                                                 {
                                                                     f.ImageUrl,
                                                                     f.ImageWidth,
                                                                     f.ImageHeight,
                                                                     f.Domain,
                                                                 }
                                                                     into gfeeds
                                                                     select new WebApp1.Controllers.FeedGroup
                                                                     {
                                                                         Feeds = gfeeds.ToList(),
                                                                         Date = gfeeds.Max(f => f.PubDate),
                                                                         ImageUrl = gfeeds.Key.ImageUrl,
                                                                         ImageHeight = gfeeds.Key.ImageHeight,
                                                                         ImageWidth = gfeeds.Key.ImageWidth,
                                                                         Domain = gfeeds.Key.Domain
                                                                     }).ToList();




            remaingGroups.AddRange(groups);



            remaingGroups = (from rg in remaingGroups
                             orderby rg.Score descending
                             select rg).ToList();


            return remaingGroups;

            //foreach (var item in resultedStrongFeedConnections)
            //{
            //    Response.Write("<br/>" + item.Source + " - " + item.Destination + " - " + item.Score);
            //    if (item.Score > 0)
            //    {
            //        var selectedFeeds = feeds.Where(f => f.ID == item.Destination || f.ID == item.Source).ToList();

            //        foreach (var sFeed in selectedFeeds)
            //        {
            //            Response.Write("<br/>" + sFeed.Title);
            //        }
            //    }
            //}

        }
    }

}